/**
 * 短信相关接口
 */
import CryptoJS from 'crypto-js';
import SMSClient from '@alicloud/sms-sdk';
import models from '../db/sequelize';

let smsClient = null;

/**
 * 初始化短信发送客户端，若有则取，若无则创建
 */
const getSmsClient = async () => {
  const config = (await models.m_config.findOne({
    attributes: ['value'],
    where: { key: 'aliyun' },
    raw: true
  })).value;

  if (config.access_key_id && config.access_key_secret && !smsClient) {
    try {
      smsClient = new SMSClient({ accessKeyId: config.access_key_id, secretAccessKey: config.access_key_secret });
    } catch (e) {
      console.error('初始化短信出错', e);
    }
  }
  return smsClient;
}
// 生成6位随机数
const generateSixDigitRandom = () => {
  // 生成一个随机的32位整数
  const randomInt = CryptoJS.lib.WordArray.random(4).toString(CryptoJS.enc.Hex);

  // 将32位整数转换为10进制
  const randomDecimal = parseInt(randomInt, 16);

  // 取模运算，确保结果在0到999999之间
  const sixDigitNumber = randomDecimal % 1000000;

  // 确保结果是6位数字，不足6位时前面补0
  return String(sixDigitNumber).padStart(6, '0');
};

// 清除leveldb中过期的短信验证码
const clearExpiredVerCode = async () => {
  const now = Date.now();
  try {
    const iterator = global.levelDB.iterator();

    for await (const [key, value] of iterator) {
      if (key.startsWith('sms_') && value.expiresAt < now) {
        await global.levelDB.del(key);
      }
    }
  } catch (e) {
    console.error('清除leveldb中过期的短信验证码出错', e);
  }
}
/**
 * 发送验证短信
 * @param {string} phone 手机号码
 * @param {object} params 参数
 */
export const sendVerCode = async (phone) => {
  const config = (await models.m_config.findOne({
    attributes: ['value'],
    where: { key: 'aliyun' },
    raw: true
  })).value;

  if (!/^1[3-9]\d{9}$/.test(phone)) {
    return { result: 'fail', message: '无效的手机号' };
  }

  const client = await getSmsClient();

  if (!config.sms_template || !config.sms_template.reg_ver || !client) {
    return { result: 'fail', message: '短信配置错误' };
  }

  const code = generateSixDigitRandom(); // 6位随机数

  await clearExpiredVerCode(); // 清除过期数据

  let data = null;
  try {
    data = await global.levelDB.get(`sms_${phone}`);
  } catch (e) {
    console.log(`无 sms_${phone}`);
  }

  if (data) {
    return { result: 'fail', message: '验证码还处于有效期内，请勿频繁发送' };
  }

  global.levelDB.put(`sms_${phone}`, { code, expiresAt: Date.now() + 60 * 1000 * 10 }); // 存入leveldb，有效期10分钟

  let result = { result: 'ok' };
  try {
    const ret = await client.sendSMS({
      PhoneNumbers: phone,
      SignName: config.sms_sign_name,
      TemplateCode: config.sms_template.reg_ver.code,
      TemplateParam: JSON.stringify({ code })
    });
    console.log(phone, code, ret);
  } catch (error) {
    console.error('短信发送失败', error)
    result = { result: 'fail', message: '短信发送失败' };
  }
  return result;
}

/**
 * 校验短信验证码
 * @param {string} phone 手机号码
 * @param {string} code 验证码
 */
export const checkVerCode = async (phone, code) => {
  await clearExpiredVerCode(); // 清除过期数据
  const key = `sms_${phone}`;
  let data = null;
  try {
    data = await global.levelDB.get(key);
  } catch (e) {
    console.log(`无 sms_${phone}`);
  }

  if (data && data.code === String(code)) {
    global.levelDB.del(key);
    return { result: 'ok' }
  }
  return { result: 'fail', message: '验证码不正确' };
}

export default { sendVerCode, checkVerCode }
